/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package torrent;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.net.DatagramSocket;
import java.net.SocketAddress;
import java.net.SocketException;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author THIEUQUANG
 */
public class Function implements Runnable {

    private static SocketAddress tempsock = null;
    private static volatile boolean running = true;
    public static int Chunkstat = 0;
    public static int fileSize = 0;
    public static int numChunk = 0;
    public static ArrayList<String> hash = new ArrayList<String>();
    public static String FileNameTorrent = null;
    boolean Value = false;
    public static DatagramSocket utpSocket = null;// FIXED
    public static DatagramSocket utpSocket2 = null;
    public static Thread ana = null;
    static int[] chunkstate = new int[1000];
    public static Thread t;

    public Function() {
         t = new Thread(this);
    }

    public static void main(String[] args) throws IOException, InterruptedException {

    }

    public static void initsock() throws SocketException {
        utpSocket2 = new DatagramSocket(3500);
        utpSocket = new DatagramSocket(3400);
    }

    public void Chay() throws SocketException, IOException {
        initsock();

        if (FileNameTorrent != null) {
            while (true) {
                if (check(FileNameTorrent, numChunk) == numChunk) {
                   JoinFile(fileSize, numChunk - 1, FileNameTorrent);
                    break;
                }
                try {

                    for (int i = 1; i <= numChunk; i++) {
                        synchronized (t) {
                            if (running == false) {
                                t.wait();
                            }
                        }
                        if (chunkstate[i] == 0) {
                            Thread t = new Thread(new Controller(FileNameTorrent, i));
                            t.start();
                        }
                       // Thread.sleep(500);
                    }
                    Thread.sleep(5000);
                } catch (InterruptedException ex) {
                    Logger.getLogger(Function.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        } else {
            Thread t = new Thread(new Controller("", 1));
            t.start();
        }

    }

    public static void stopthread() {
        ana.interrupt();
    }

    public static String PreCreateChunk(String filename) {
        String dir = System.getProperty("user.dir");

        dir = dir + "\\rsc";
        File file = new File(dir);
        //Tạo thư mục rsc chứa các chunk
        file.mkdir();

        return dir;
    }

    /**
     * Tạo Chunk
     */
    public static void CreateChunk(String Filename) {
        try {
            //Lấy tên file, lấy chiều dài file
            File fi = new File(Filename);
            long FILE_SIZE = (long) fi.length();

            System.out.println("Filesize: " + FILE_SIZE);
            //Tạo mảng byte chứa 1 chunk
            byte[] sentBuf = new byte[524288];
            int len = 1;
            int chunknum = 0;

            //tạo thư mục src
            String str = PreCreateChunk(Filename);
            //Tạo file torrent
            File f = new File(Filename + ".torrent");

            //Gán đường dẫn đến thư mục src
            str = str + "\\" + f.getName();
            while (len > 0) {
                BufferedWriter bw = null;
                FileWriter fw = new FileWriter(str, true);
                bw = new BufferedWriter(fw);
                FileInputStream fis = new FileInputStream(Filename);
                ByteArrayOutputStream bos = new ByteArrayOutputStream();
                FileOutputStream fos = null;
                System.out.println("Filesize: " + chunknum);

                //Ghi file size xuống torrent
                bw.write(Long.toString(FILE_SIZE));
                bw.newLine();
                long estchunk = FILE_SIZE / 524288;

                // ghi so luong chunk-1 vao file(neu file mod 512kb!=0)
                bw.write(Long.toString(estchunk));
                bw.newLine();
                long readbyte = 0;
                while ((len = fis.read(sentBuf, 0, 524288)) > 0) {
                    //doc 512kb gan vo sentbuf
                    chunknum++;
                    MessageDigest md = MessageDigest.getInstance("SHA-1");
                    md.update(sentBuf, 0, 524288);
                    byte[] mdbytes = md.digest();
                    StringBuffer hexString = new StringBuffer();
                    for (int i = 0; i < mdbytes.length; i++) {
                        hexString.append(Integer.toHexString(0xFF & mdbytes[i]));
                    }
                    String writevalue = hexString.toString();

                    bw.write(writevalue);
                    bw.newLine();
                    bw.flush();

                    // ghi xuong bos, hinh nhu cho nay ko van thiet
                    bos.write(sentBuf, 0, 524288);
                    String[] temp = str.split("\\.torrent");
                    str = temp[0];
                    fos = new FileOutputStream(new File(str + "."
                            + chunknum + ".chunk"));
                    fos.write(sentBuf);
                    fos.flush();
                }
                fis.close();
                fos.close();
                bw.close();
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void JoinFile(long filesize, int chunknum, String Filename)
            throws IOException {
        // tinh so byte le(phan du cuafilesize mod 512kb)
        int remainbyte = (int) (filesize - (chunknum * 524288));
        // so byte dung cua file
        byte[] readbuf = new byte[(524288 * chunknum) + remainbyte];
        int i = 1;
        long len;
        int readbyte = 0;
        FileInputStream fis = null;
        FileOutputStream fos = new FileOutputStream("rsc\\" + Filename);
        while (i <= chunknum) {
            // noi file tu chunk 1 den n-1
            fis = new FileInputStream("rsc\\" + Filename + "." + i + ".chunk");
            len = fis.read(readbuf, readbyte, 524288);
            readbyte += len;
            i++;
        }
        chunknum++;
        // noi chunk cuoi cung (tach chunk cuoi ra xu ly rieng)
        fis = new FileInputStream("rsc\\" + Filename + "." + chunknum + ".chunk");
        len = fis.read(readbuf, readbyte, remainbyte);
        fos.write(readbuf);
        fos.close();
        fis.close();
    }

    public static void ReadTorrent(String FileName) throws FileNotFoundException, IOException {
        //Chứa kích thước file, số chunk, và danh sách các mã hash
        File f = new File(FileName);

        String[] temp = f.getName().split("\\.torrent");
        FileNameTorrent = temp[0];

        String hashString = null;

        BufferedReader br = new BufferedReader(new FileReader(f));
        fileSize = Integer.parseInt(br.readLine());
        numChunk = Integer.parseInt(br.readLine());
        numChunk++; //Cong them chunk cuoi
        for (int i = 0; i < numChunk; i++) {
            hashString = br.readLine();
            hash.add(hashString);
        }

        br.close();
    }

    public static int check(String filename, int chunknum) {
        int allsuccess = 0;

        File fi = new File("rsc//");
        String[] List;
        List = fi.list();
        boolean flag = false;
        for (int i = 1; i <= chunknum; i++) {
            for (String List1 : List) {
                // kiem tra xem co ton tai file dang dc yeu cau
                if (List1.toString().equals(filename + "." + i + ".chunk")) {
                    chunkstate[i] = 1;
                    allsuccess++;
                    break;
                }
            }
        }
        return allsuccess;
    }

    public void resume() {
        synchronized (t) {
            t.notify();
            running = true;
        }
    }

    public void pause() throws InterruptedException {
        running = false;
        Thread.sleep(20000);
        resume();
    }

    @Override
    public void run() {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

}
